package cn.itsource.hrm.service.impl;

import cn.itsource.hrm.constant.RedisConstant;
import cn.itsource.hrm.domain.CourseType;
import cn.itsource.hrm.domain.vo.CourseTypeVO;
import cn.itsource.hrm.mapper.CourseTypeMapper;
import cn.itsource.hrm.service.ICourseTypeService;
import cn.itsource.hrm.util.ValidityUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author gwkge
 * @since 2021-04-03
 */
@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {
    
    
    
    
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;



//    =================================================================
    @Override
    public List<CourseTypeVO> crumbs(Long courseTypeId) {
        //根据分类ID 查询面包屑 
        List<CourseTypeVO> result = new ArrayList<>();
        
        //1. 根据id，查询path   //1037.1039.1040
        ValidityUtils.isNotNull(courseTypeId, "课程id不存在！！！");
        CourseType courseType = baseMapper.selectById(courseTypeId);
        ValidityUtils.isNotNull(courseType, "课程分类，不存在！！！");
        
        //2. 拆分 path [1037 , 1039, 1040 ]
        String path = courseType.getPath();
        String[] ids = path.split("\\.");

        //3. 遍历数组，查询对应id的分类信息
        List<String> list = Arrays.asList(ids);
        list.forEach(idstr ->{
            Long id  = Long.valueOf(idstr);
            CourseType courseType1 = baseMapper.selectById(id);
            //4. 根据分类信息 查询拥有相同pid的分类，集合
            List<CourseType> courseTypes = baseMapper.selectByPId(courseType1.getPid());

            CourseTypeVO courseTypeVO = new CourseTypeVO();
            courseTypeVO.setOwnerProductType(courseType1);
            courseTypeVO.setOtherProductTypes(courseTypes);

            result.add(courseTypeVO);
        });
        
        //5. 返回 查询出来的 分类集合
        return result;
    }

public static void main(String[] args){
    String p = "1037.1039.1040";
    String[] split = p.split("\\.");
    System.out.println(Arrays.toString(split));

}



//  分类查询和缓存  =================================================================  
    
    @Override
    @CacheEvict(cacheNames=RedisConstant.COURSE_TYP_CONSTANT,key = "'all'")
    public boolean insert(CourseType entity) {
        
        return super.insert(entity);
    }

    @Override
    @CacheEvict(cacheNames=RedisConstant.COURSE_TYP_CONSTANT,key = "'all'")
    public boolean deleteById(Serializable id) {
        return super.deleteById(id);
    }

    @Override
    @CacheEvict(cacheNames=RedisConstant.COURSE_TYP_CONSTANT,key = "'all'")
    public boolean updateById(CourseType entity) {
        return super.updateById(entity);
    }

   
    /**
     * 通过Redis注解实现 课程分类的缓存
     * @return List<CourseType> tree 
     */
    @Override
    @Cacheable(cacheNames=RedisConstant.COURSE_TYP_CONSTANT,key = "'all'")
    public List<CourseType> treeData() {
        return getTypeBySelf();
    }

    /**
     * 通过Redis手动实现 课程分类的缓存
     * @return List<CourseType> tree 
     */
    public List<CourseType> treeData2() {
        //1. 先 查询Redis 中是否有课程分类，opsforValue.get （key）
        //1.1  需要准备RedisKey 的 常量
        List<CourseType> treeData = (List<CourseType>)redisTemplate.opsForValue().get(RedisConstant.COURSE_TYP_CONSTANT);
        
        //2. 如果没有，在到数据库中进行查询
        if(treeData!=null){
            return  treeData;   
        }
        List<CourseType> types = getTypeBySelf();
        //3. 把查询到的结果，保存到Redis ，opsforValue.set( key, value)，通过Redis序列化
        //3. 1. 添加序列化的配置文件
        redisTemplate.opsForValue().set(RedisConstant.COURSE_TYP_CONSTANT, types);
        
        return types;

    }
    
    /**
     * 没有使用Redis缓存的 方法
     * 1. 先找到第一级分类(pid==0)
     * 2. 遍历第一级分类，找到pid和一级分类id相同的分类（二级分类）
     * 3. 遍历第二级分类，找到pid和二级分类id相同的分类（三级分类）
     * 4. .... 递归查询 （效率太低了... ）
     * @return List<CourseType> tree 
     */
    public List<CourseType> treeDataOld() {
        
        //return getTypeListBySQl();
        return getTypeBySelf();
        
    }

    private List<CourseType> getTypeBySelf() {
        //1. 只发一次sql，把所有的分类查询出来
        // EntityWrapper<CourseType> wrapper = new EntityWrapper<>();
        List<CourseType> allTypes = baseMapper.selectList(null);

        //2. 在代码中，判断找到一级分类
        List<CourseType> firestType = new ArrayList<>();
        allTypes.forEach(type ->{
            if(type.getPid().equals(0L)){
                //一级分类 
                firestType.add(type);
            }else{
                //3. 在其他分类,到所有分类中去找自己的上一级分类
                for (CourseType allType : allTypes) {
                    if(type.getPid().equals(allType.getId())){
                        allType.getChildren().add(type);
                    }
                }
            }
        });
      
        //4. 最后返回一级分类就可以类
        return firestType;

    }

    private List<CourseType> getTypeListBySQl() {
        List<CourseType> tree = baseMapper.selectByPId(0L);
        return tree;
    }
}
